package com.xiaoyuan.minicore.mvc;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.xiaoyuan.minicore.aop.AOPHelper;
import com.xiaoyuan.minicore.ioc.BeanHelper;
import com.xiaoyuan.minicore.mvc.bean.ActionBean;
import com.xiaoyuan.minicore.mvc.bean.RequestBean;
import com.xiaoyuan.minicore.mvc.bean.Result;
import com.xiaoyuan.minicore.util.StringUtil;
import com.xiaoyuan.minicore.util.WebUtil;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xiaoyuan.minicore.ioc.IOCHelper;
/**
 * @Auther: xiaoyuan
 * @Date: 2020/4/28
 * @Description: 前端路由控制器，所有的请求从这儿分发出去
 */
@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

    private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);

    private static final  ObjectMapper objectMapper = new ObjectMapper();

    private static final Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();

    public DispatcherServlet(){
        super();
        AOPHelper.init();
        BeanHelper.init();
        ActionHelper.init();
        IOCHelper.init();
    }

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取当前请求相关数据
        String currentRequestMethod = request.getMethod();
        String currentRequestURL = request.getPathInfo();
        logger.info("-------------------------------------------------------->");
        logger.info("请求地址:{},请求方式：{}", currentRequestURL, currentRequestMethod);
        logger.info("请求参数：{}", objectMapper.writeValueAsString(request.getParameterMap()));
        logger.info("<--------------------------------------------------------");
        // 屏蔽特殊请求
        if (currentRequestURL.equals("/favicon.ico")) {
            return;
        }
        // 获取并遍历 Action 映射
        Map<RequestBean, ActionBean> actionMap = ActionHelper.getActionMap();
        //
        logger.info("--------------------------------------------------------");

        for (Map.Entry<RequestBean, ActionBean> actionEntry : actionMap.entrySet()) {
            // 从 RequestBean 中获取 Request 相关属性
            RequestBean reqestBean = actionEntry.getKey();
            String requestURL = reqestBean.getRequestURL(); // 正则表达式
            String requestMethod = reqestBean.getRequestMethod();
            // 获取正则表达式匹配器（用于匹配请求 URL 并从中获取相应的请求参数）
            Matcher matcher = Pattern.compile(requestURL).matcher(currentRequestURL);
            // 判断请求方法与请求 URL 是否同时匹配
            if (requestMethod.equals(currentRequestMethod) && matcher.matches()) {
                // 初始化 Action 对象
                ActionBean actionBean = actionEntry.getValue();
                // 初始化 Action 方法参数列表
                List<Object> paramList = new ArrayList<Object>();
                for (int i = 1; i <= matcher.groupCount(); i++) {
                    String param = matcher.group(i);
                    // 若为数字，则需要强制转换，并放入参数列表中
                    if (StringUtil.isDigits(param)) {
                        paramList.add(Long.parseLong(param));
                    } else {
                        paramList.add(param);
                    }
                }
                // 从 ActionBean 中获取 Action 相关属性
                Class<?> actionClass = actionBean.getActionClass();
                Method actionMethod = actionBean.getActionMethod();
                try {
                    // 创建 Action 实例
                    Object actionInstance = actionClass.newInstance();
                    //将action中的@inject处理掉
                    IOCHelper.inject(actionClass,actionInstance,beanMap);
                    // 调用 Action 方法（传入请求参数）
                    Object actionMethodResult = actionMethod.invoke(actionInstance, paramList.toArray());
                    if (actionMethodResult instanceof Result) {
                        // 获取 Action 方法返回值
                        Result result = (Result) actionMethodResult;
                        // 将返回值转为 JSON 格式并写入 Response 中
                        WebUtil.writeJSON(response, result);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 若成功匹配，则终止循环
                break;
            }
        }
    }
}
